
module mbox.Sender;
import mbox.Types;



struct Smtp_Sender {
	static Thread 	_th ;
	static char[]	_ehlo ;
	
	static void Init(){
		_th		= new Thread(&Run);
		_ehlo		=  "EHLO " ~ MyConf.host ;
	}
	
	static void Start(){
		_th.start ;
	}
	
	static void Run () {
		while( MyBox.isRunning.load() ){
			scope p = MyBox.peek() ;
			if( p is null ){
				GC.minimize ;
				version(DEV){
					Stdout.formatln("{} start wait :{}", __LINE__, MyConf.try_delay ).flush;
				}
				MyBox.sem.wait( MyConf.try_delay + 1 ) ;
				version(DEV){
					Stdout.formatln("{} wait done", __LINE__).flush;
				}
				continue;
			}
			version(DEV){
				Stdout.formatln("{} send to remote", __LINE__ ).flush;
			}
			Send(p);
			MyBox.update(p);
			delete p;
			Thread.sleep( 1 );
		}
		Stdout.formatln("Sender Thread Finish.").flush;
	}
	
	static void Send(MyBox.Row* p) {
		
		p._trys++ ;
		p._next	= Clock.now.unix.seconds   + p._trys *  MyConf.try_delay ;
		p._last	= Clock.now.unix.seconds ;
		
		scope soc	= new Socket;
		
		char[] _from	= Txt.trim(p.sFrom) ;
		if( _from.length > 0 && _from[0] is '<' )		_from	= _from[1..$];
		if( _from.length > 0 && _from[$-1] is '>' )	_from	= _from[0..$-1];
		_from	= Txt.trim(_from) ;
		if( _from.length > 0 && _from[0] is '"' )		_from	= _from[1..$];
		if( _from.length > 0 && _from[$-1] is '"' )	_from	= _from[0..$-1];

		char[] _to		= p.sTo ;
		{
			int	i	= find(_to, '<' );
			int	j	= find(_to, '>' );
			if( i >=0 && i  < _to.length &&  j > 0 && j <= _to.length && i < j ){
				_to	= Txt.trim( _to[ i +1 .. j ] ) ;
			}
				
			if( !contains(_to, '@') || contains(_to, '<') ||  contains(_to, '>') ||  contains(_to, '"') ||  contains(_to, '\'') ){
				Stdout.formatln("无效的Email:{} !\n" , _to ).flush;
				p.isDone	= 1 ;
				return  ;
			}

		}
		
		char[] addr	= MyDns.Query( _to ) ;
		if( addr is null ) {
			Stdout.formatln("无法获得地址:`{}` ", _to);
			p.isDone	= 1 ;
			return ;
		}
		
		Address	_addr		= new InternetAddress( addr  , 25 ) ;
		
		scope( exit ){
			if( p.isDone ){
				Stdout("发送成功!\n" ).flush;
			}else{
				Stdout("发送失败!\n" ).flush;
			}
		}
		
		/*
			char[] _title	= cast(char[]) p.sBody ;
			_title	= _title[ 0 .. find(_title, '\n' ) ];
			_title	= Txt.trim( _title[ find(_title, ':' ) + 1  .. $ ] ) ;
		*/
		
		Stdout.formatln("\nDate: {}	ID: {}",  TimS.toString(Time.epoch1970 +TimeSpan.fromSeconds(p._last) ),  p.ROWID).flush ;
		Stdout.formatln("发送给: {}", p.sTo ).flush ;
		
		if(   MyConf.only_user  !is null &&   MyConf.only_user .length > 3 && _to != MyConf.only_user ) {
			Stdout.formatln("\n从{}发送邮件到{}失败， 只能给{}发送。", _from, _to, MyConf.only_user );
			p.isDone	= 1 ;
			return ;
		}
		
		
		if(  p._trys  > 1 ){
			Stdout.formatln("第{}次发送", p._trys ).flush ;
		}
		
		try{
			soc.connect(_addr);
		}catch(Object o) {
			return ;
		}
		Stdout("已连接到: ")(addr)("\n").flush;
		scope(exit) {
			soc.close;
		}
		scope ls	=  LineSocket.Init(soc); 
		char[] val;
		
		if( !get(220, ls, val) ){
			return ;
		}
		
		ls.put( _ehlo ) ;
		
		ubyte[512] tmp ;
		int i	= ls.read(tmp);
		
		version(DEV){
			Stdout.formatln("{}", cast(char[]) tmp [0..i]);
		}
		
		ls.put( "mail from: <" ~ _from ~ ">" ) ;	
		ls.get;
		
		ls.put( "rcpt to: <" ~ _to ~ ">" ) ;
		ls.get;
		
		ls.put("DATA");
		ls.get;
		
		ls.write( p.sBody );
		if( !get(250, ls, val) ){
			return ;
		}
		
		p.isDone	= 1 ;
		ls.put("QUIT");
		ls.get;
	}
	
	static bool get(int cmd, LineSocket* ls, ref char[] val){
		val	= ls.get;
		int _cmd	= Int.parse(val);
		return _cmd == cmd ;
	}
}